#!/bin/bash

# Matrix Framework 生产环境安全配置生成脚本
# 用于生成生产环境所需的安全密钥和配置文件

set -euo pipefail

# 颜色输出定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 日志函数
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# 检查依赖
check_dependencies() {
    log_info "检查系统依赖..."

    local missing_deps=()

    if ! command -v openssl &> /dev/null; then
        missing_deps+=("openssl")
    fi

    if ! command -v docker &> /dev/null; then
        missing_deps+=("docker")
    fi

    if ! command -v jq &> /dev/null; then
        missing_deps+=("jq")
    fi

    if [ ${#missing_deps[@]} -ne 0 ]; then
        log_error "缺少依赖: ${missing_deps[*]}"
        log_info "请安装缺少的依赖后重新运行脚本"
        exit 1
    fi

    log_success "依赖检查完成"
}

# 生成随机字符串
generate_random_string() {
    local length=${1:-32}
    openssl rand -hex $((length / 2)) | cut -c1-$length
}

# 生成安全的密码
generate_secure_password() {
    local length=${1:-32}

    # 生成包含大小写字母、数字和特殊字符的密码
    openssl rand -base64 48 | tr -d "=+/" | cut -c1-$length
}

# 生成JWT密钥
generate_jwt_key() {
    openssl rand -hex 32
}

# 生成数据库密码
generate_db_password() {
    generate_secure_password 32
}

# 生成Redis密码
generate_redis_password() {
    generate_secure_password 32
}

# 生成MinIO密钥
generate_minio_keys() {
    local access_key="matrix$(openssl rand -hex 4 | tr '[:lower:]' '[:upper:]')"
    local secret_key=$(generate_secure_password 40)

    echo "$access_key:$secret_key"
}

# 生成Consul令牌
generate_consul_token() {
    openssl rand -base64 32 | tr -d "=+/" | cut -c1-32
}

# 生成Consul加密密钥
generate_consul_encryption_key() {
    openssl rand -hex 16
}

# 生成API令牌
generate_api_token() {
    openssl rand -base64 32 | tr -d "=+/" | cut -c1-32
}

# 生成自签名SSL证书
generate_ssl_certificates() {
    local domain=${1:-matrix.com}
    local config_dir=${2:-./ssl}

    log_info "为域名 $domain 生成SSL证书..."

    mkdir -p "$config_dir"

    # 生成私钥
    openssl genrsa -out "$config_dir/matrix.com.key" 2048

    # 生成证书签名请求
    openssl req -new -key "$config_dir/matrix.com.key" -out "$config_dir/matrix.com.csr" -subj "/C=CN/ST=Beijing/L=Beijing/O=MatrixFramework/OU=IT/CN=$domain"

    # 生成自签名证书
    openssl x509 -req -days 365 -in "$config_dir/matrix.com.csr" -signkey "$config_dir/matrix.com.key" -out "$config_dir/matrix.com.crt"

    # 生成CA证书（用于内部服务通信）
    openssl genrsa -out "$config_dir/ca.key" 2048
    openssl req -new -x509 -key "$config_dir/ca.key" -out "$config_dir/ca.crt" -days 3650 -subj "/C=CN/ST=Beijing/L=Beijing/O=MatrixFramework/OU=IT/CN=MatrixFramework CA"

    # 生成Keycloak证书
    openssl genrsa -out "$config_dir/keycloak.key" 2048
    openssl req -new -key "$config_dir/keycloak.key" -out "$config_dir/keycloak.csr" -subj "/C=CN/ST=Beijing/L=Beijing/O=MatrixFramework/OU=IT/CN=auth.$domain"
    openssl x509 -req -days 365 -in "$config_dir/keycloak.csr" -CA "$config_dir/ca.crt" -CAkey "$config_dir/ca.key" -CAcreateserial -out "$config_dir/keycloak.crt"

    # 生成Consul证书
    openssl genrsa -out "$config_dir/consul.key" 2048
    openssl req -new -key "$config_dir/consul.key" -out "$config_dir/consul.csr" -subj "/C=CN/ST=Beijing/L=Beijing/O=MatrixFramework/OU=IT/CN=consul.$domain"
    openssl x509 -req -days 365 -in "$config_dir/consul.csr" -CA "$config_dir/ca.crt" -CAkey "$config_dir/ca.key" -CAcreateserial -out "$config_dir/consul.crt"

    # 生成PKCS12格式证书（用于.NET应用）
    openssl pkcs12 -export -out "$config_dir/cert.pfx" -inkey "$config_dir/matrix.com.key" -in "$config_dir/matrix.com.crt" -certfile "$config_dir/ca.crt" -passout pass:$(generate_secure_password 16)

    # 设置正确的权限
    chmod 600 "$config_dir"/*.key
    chmod 644 "$config_dir"/*.crt
    chmod 600 "$config_dir"/*.pfx

    log_success "SSL证书生成完成"
}

# 生成生产环境配置文件
generate_production_config() {
    local env_file=".env.production"
    local domain=${1:-matrix.com}

    log_info "生成生产环境配置文件..."

    if [ -f "$env_file" ]; then
        log_warning "文件 $env_file 已存在，将创建备份"
        cp "$env_file" "$env_file.backup.$(date +%Y%m%d_%H%M%S)"
    fi

    cat > "$env_file" << EOF
# =============================================================================
# Matrix Framework 生产环境配置
# 自动生成时间: $(date)
# 域名: $domain
# =============================================================================

# 数据库配置
DB_PASSWORD=$(generate_db_password)
DB_USER=matrix_user

# Redis配置
REDIS_PASSWORD=$(generate_redis_password)

# 加密和安全密钥
ENCRYPTION_KEY=$(generate_random_string 32)
JWT_SIGNING_KEY=$(generate_jwt_key)
PASSWORD_SALT=$(generate_random_string 32)
SSL_CERT_PASSWORD=$(generate_secure_password 16)

# 认证配置
KEYCLOAK_ADMIN=admin
KEYCLOAK_ADMIN_PASSWORD=$(generate_secure_password 16)
KEYCLOAK_REALM=matrix-prod
KEYCLOAK_CLIENT_ID=matrix-web-app
KEYCLOAK_CLIENT_SECRET=$(generate_api_token)

# 对象存储配置
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=$(generate_minio_keys | cut -d: -f2)

# 服务网格配置
CONSUL_TOKEN=$(generate_consul_token)
CONSUL_GOSSIP_ENCRYPTION_KEY=$(generate_consul_encryption_key)

# 管理员API令牌
ADMIN_TOKEN=$(generate_api_token)

# API限流配置
API_RATE_LIMIT=1000
TENANT_API_RATE_LIMIT=500
USER_API_RATE_LIMIT=2000
PHOTO_API_RATE_LIMIT=1000

# 域名和SSL配置
DOMAIN_NAME=$domain
SSL_CERTIFICATE_PATH=/ssl/matrix.com.crt
SSL_PRIVATE_KEY_PATH=/ssl/matrix.com.key
SSL_CA_CERTIFICATE_PATH=/ssl/ca.crt

# 监控配置
GRAFANA_ADMIN_PASSWORD=$(generate_secure_password 16)

# 告警配置
ALERT_EMAIL_FROM=alerts@$domain
ALERT_EMAIL_TO=admin@$domain

# 性能配置
LOG_LEVEL=Warning
SESSION_TIMEOUT_MINUTES=60
JWT_EXPIRATION_MINUTES=60

# 安全策略
PASSWORD_MIN_LENGTH=12
PASSWORD_MAX_FAILED_ATTEMPTS=5
PASSWORD_LOCKOUT_MINUTES=30
CORS_ALLOWED_ORIGINS=https://$domain,https://admin.$domain

# 环境标识
ENVIRONMENT=Production
DEPLOYMENT_VERSION=1.0.0
EOF

    log_success "生产环境配置文件生成完成: $env_file"
}

# 生成安全配置文档
generate_security_documentation() {
    local doc_file="SECURITY_DOCUMENTATION.md"

    log_info "生成安全配置文档..."

    cat > "$doc_file" << EOF
# Matrix Framework 生产环境安全配置文档

## 概述

本文档记录了Matrix Framework生产环境的安全配置和最佳实践。

## 生成的安全配置

### 数据库安全
- **数据库密码**: 自动生成的32位强密码
- **连接加密**: 强制SSL连接
- **网络隔离**: 数据库仅在内部网络可访问

### Redis缓存安全
- **Redis密码**: 自动生成的32位强密码
- **SSL加密**: 启用Redis SSL连接
- **认证**: 要求密码认证

### 证书和密钥
- **SSL证书**: 自签名证书用于内部服务通信
- **JWT密钥**: 32字节随机密钥用于JWT签名
- **加密密钥**: 32字节密钥用于数据加密

### 服务认证
- **Consul令牌**: 自动生成的管理令牌
- **API令牌**: 管理员API访问令牌
- **Keycloak**: 企业级身份认证

## 安全最佳实践

### 1. 密码管理
- 所有密码都使用强随机生成
- 定期轮换所有密码（建议每90天）
- 使用密码管理器存储密码
- 不要在代码中硬编码密码

### 2. 证书管理
- 使用权威CA签名的证书用于生产环境
- 定期更新证书（建议每年）
- 监控证书过期时间
- 使用证书管理工具

### 3. 网络安全
- 使用VPC隔离网络
- 配置防火墙规则
- 启用DDoS防护
- 使用VPN进行远程访问

### 4. 监控和告警
- 监控所有安全相关事件
- 配置实时告警
- 定期安全审计
- 保留日志足够长时间

### 5. 备份和恢复
- 定期备份所有数据
- 加密备份数据
- 测试恢复流程
- 异地备份存储

## 应急响应

### 安全事件响应流程
1. 检测和识别
2. 隔离和遏制
3. 调查和分析
4. 根除和恢复
5. 总结和改进

### 紧急联系方式
- 系统管理员: [联系方式]
- 安全团队: [联系方式]
- 管理层: [联系方式]

## 合规性要求

### GDPR合规
- 数据保护影响评估
- 数据主体权利响应
- 数据泄露通知流程
- 数据保护官指定

### 其他合规要求
- SOX合规性要求
- 行业特定合规要求
- 地区性数据保护法规

## 定期维护任务

### 每日任务
- 检查系统安全日志
- 监控异常活动
- 备份状态检查

### 每周任务
- 安全补丁更新
- 证书过期检查
- 权限审查

### 每月任务
- 密码轮换
- 安全审计
- 威胁情报更新

### 每季度任务
- 渗透测试
- 安全培训
- 应急响应演练

## 联系信息

如有安全问题，请联系：
- 邮箱: security@matrix.com
- 紧急电话: [紧急电话]
- 安全门户: https://security.matrix.com

---

*此文档随配置自动生成，请定期更新*
EOF

    log_success "安全配置文档生成完成: $doc_file"
}

# 生成Docker安全配置
generate_docker_security_config() {
    log_info "生成Docker安全配置..."

    # 创建安全配置文件
    cat > "docker-security.conf" << EOF
# Docker安全配置

# 用户配置
user matrix-user

# 资源限制
limit nofile 65536
limit nproc 4096

# 安全内核参数
net.core.somaxconn = 65536
net.ipv4.tcp_max_syn_backlog = 65536
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_max_tw_buckets = 5000

# 文件系统安全
fs.file-max = 100000
fs.inotify.max_user_watches = 524288

# 内存安全
vm.swappiness = 10
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
EOF

    log_success "Docker安全配置生成完成"
}

# 验证配置
validate_configuration() {
    log_info "验证配置..."

    local errors=0

    # 检查必需文件
    local required_files=(".env.production ssl/ca.crt ssl/matrix.com.crt ssl/matrix.com.key")

    for file in $required_files; do
        if [ ! -f "$file" ]; then
            log_error "缺少必需文件: $file"
            ((errors++))
        fi
    done

    # 检查环境变量
    if [ ! -f ".env.production" ]; then
        log_error "缺少生产环境配置文件"
        ((errors++))
    fi

    # 检查SSL证书
    if [ -f "ssl/matrix.com.crt" ]; then
        local cert_days
        cert_days=$(openssl x509 -in "ssl/matrix.com.crt" -noout -dates 2>/dev/null | grep "notAfter" | cut -d= -f2)
        if [ -n "$cert_days" ]; then
            local expiry_date=$(date -d "$cert_days" +%s)
            local current_date=$(date +%s)
            local days_until_expiry=$(( (expiry_date - current_date) / 86400 ))

            if [ $days_until_expiry -lt 30 ]; then
                log_warning "SSL证书将在 $days_until_expiry 天后过期"
            fi
        fi
    fi

    if [ $errors -eq 0 ]; then
        log_success "配置验证通过"
    else
        log_error "配置验证失败，发现 $errors 个错误"
        return 1
    fi
}

# 主函数
main() {
    local domain=${1:-matrix.com}

    echo "======================================================"
    echo "Matrix Framework 生产环境安全配置生成器"
    echo "======================================================"
    echo "目标域名: $domain"
    echo "生成时间: $(date)"
    echo "======================================================"

    # 创建目录结构
    mkdir -p ssl config logs backups

    # 执行生成步骤
    check_dependencies
    generate_ssl_certificates "$domain"
    generate_production_config "$domain"
    generate_security_documentation
    generate_docker_security_config

    # 验证配置
    validate_configuration

    echo "======================================================"
    log_success "安全配置生成完成！"
    echo "======================================================"
    echo "生成的文件："
    echo "  - .env.production          (生产环境配置)"
    echo "  - ssl/                   (SSL证书目录)"
    echo "  - SECURITY_DOCUMENTATION.md (安全配置文档)"
    echo "  - docker-security.conf    (Docker安全配置)"
    echo "======================================================"
    echo "重要提醒："
    echo "1. 请妥善保存 .env.production 文件"
    echo "2. 不要将敏感信息提交到版本控制系统"
    echo "3. 定期轮换所有密钥和密码"
    echo "4. 在生产环境中使用权威CA签名的证书"
    echo "======================================================"
}

# 脚本入口
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi